package com.qixin.activiti.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qixin.activiti.service.IEaTravelBXNCItfService;
import com.qixin.activiti.utils.EaListenerUtil;
import com.qixin.modules.ea.entity.EaBookDetail;
import com.qixin.modules.ea.entity.EaTravel;
import com.qixin.modules.ea.service.IEaBookDetailService;
import com.qixin.modules.ea.service.IEaTravelService;
import com.qixin.modules.eaBasic.service.IEaRegionService;
import com.qixin.modules.log.entity.SysInterfaceLog;
import com.qixin.modules.rzInvoice.service.IEaBillService;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.nc.enums.WSEnum;
import org.jeecg.common.nc.service.NCWebService;
import org.jeecg.common.nc.vo.WSVO;
import org.jeecg.modules.activiti.entity.ActBusiness;
import org.jeecg.modules.activiti.entity.ActZTask;
import org.jeecg.modules.activiti.service.IActZTaskService;
import org.jeecg.modules.nc.service.INcBdPsnjobService;
import org.jeecg.modules.system.service.ISysDictService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;

/***
* @Description: 差旅费用报销推送NC报销审核通过接口
* @author: CYS
* @date: 2022/3/15 11:45
*/
@Slf4j
@Service
public class EaTravelBXNCItfServiceImpl implements IEaTravelBXNCItfService {

    @Autowired
    private IEaTravelService iEaTravelService;
    @Autowired
    private IEaBookDetailService eaBookDetailService;
    @Autowired
    private IEaBillService iEaBillService;
    @Autowired
    private IActZTaskService iActZTaskService;
    @Autowired
    private INcBdPsnjobService iNcBdPsnjobService;
    @Autowired
    private ISysDictService iSysDictService;
    @Autowired
    private IEaRegionService iEaRegionService;

    @Value(value = "${qixin.ncserver.uri}")
    private  String nCUrl;

    /**
     * @param eaTravel:
     * @param eaBookDetail:
     * @param detaijsonArray:
     * @param jsonArrayBody:
     * @Description: 封装表体
     * @author: CYS
     * @date: 2022/2/23 11:12
     * @Return: void
     */
    private  void bodySet(EaTravel eaTravel, EaBookDetail eaBookDetail, JSONArray detaijsonArray, JSONArray jsonArrayBody) throws Exception {
        for (int a = 0; a < detaijsonArray.size(); a++) {
            JSONObject jsonBody = new JSONObject();
            //发票明细行税率
            BigDecimal taxRate =detaijsonArray.getJSONObject(a).getBigDecimal("taxRate").divide(new BigDecimal("100"));
            //发票明细行实际报销金额
            BigDecimal actualEaAmt=null;
            //税额
            BigDecimal tax=null;

            //飞机发票类型
            if(eaBookDetail.getType().equals("10506")){
                actualEaAmt=eaBookDetail.getActualEaAmt();
                //航空票价
                BigDecimal fare= detaijsonArray.getJSONObject(a).getBigDecimal("fare");
                //航空燃油费
                BigDecimal fuelSurcharge= detaijsonArray.getJSONObject(a).getBigDecimal("fuelSurcharge");

                tax = (fare.add(fuelSurcharge)).divide((new BigDecimal("1").add(taxRate)),2,RoundingMode.HALF_UP).multiply(taxRate);

                //火车发票类型
            }else if(eaBookDetail.getType().equals("10503")) {
                actualEaAmt=eaBookDetail.getActualEaAmt();
                tax = actualEaAmt.divide((new BigDecimal("1").add(taxRate)),2, RoundingMode.HALF_UP).multiply(taxRate);

                //住宿消费类型
            }else if(eaTravel.getIsManyBx()&&Integer.parseInt(eaBookDetail.getKind())==3){
                actualEaAmt=eaBookDetail.getActualEaAmt();
                tax = actualEaAmt.divide((new BigDecimal("1").add(taxRate)),2, RoundingMode.HALF_UP).multiply(taxRate);

            }else {
                //发票明细行实际报销金额
                BigDecimal totalAmount=detaijsonArray.getJSONObject(a).getBigDecimal("totalAmount");
                //发票明细行实际报销金额对发票总金额占比
                BigDecimal moneyNProportion=totalAmount.divide(eaBookDetail.getAmount(),2, RoundingMode.HALF_UP);
                //发票实际报销金额
                actualEaAmt=eaBookDetail.getActualEaAmt().multiply(moneyNProportion);

                tax = actualEaAmt.divide((new BigDecimal("1").add(taxRate)),2, RoundingMode.HALF_UP).multiply(taxRate);
            }

            //无税金额
            BigDecimal taxless = actualEaAmt.subtract(tax);

            // 合计金额=实际报销金额
            jsonBody.put("amount", actualEaAmt);
            // 本币金额=实际报销金额
            jsonBody.put("bbje", actualEaAmt);
            // 本币余额= -金额为0 否
            jsonBody.put("bbye", "0");
            // 冲借款本币金额= -金额为0 否
            jsonBody.put("cjkbbje", "0");
            // 冲借款金额= -金额为0 否
            jsonBody.put("cjkybje", "0");
            // 开始日期=开始日期-n
            jsonBody.put("defitem1", eaTravel.getStartDate());
            // 结束日期=结束日期
            jsonBody.put("defitem2", eaTravel.getEndDate());
            // 发票类型=发票类型表体自定义项12
            jsonBody.put("defitem12", detaijsonArray.getJSONObject(a).getString("fpTypeName"));
            // 不含税金额=不含税金额
            jsonBody.put("defitem13", taxless);
            // 税率=税率-转成NC的税码主键
            jsonBody.put("defitem14", detaijsonArray.getJSONObject(a).getString("taxCode"));
            // 税额
            jsonBody.put("defitem15", tax);
            // 删除标志=0
            jsonBody.put("dr", "0");
            // 报销人单位 =表体费用归属人单位
            jsonBody.put("dwbm", eaTravel.getCostCompCodeId());
            // 供应商=直接取表头收款人
            jsonBody.put("hbbm", eaTravel.getRecPersonId());
            // 还款本币金额= -金额为0 否
            jsonBody.put("hkbbje", "0");
            // 还款原币金额= -金额为0 否
            jsonBody.put("hkybje", "0");
            if(eaBookDetail.getFygsr().equals(eaTravel.getPersonId())){
                // 报销人部门=表体费用归属人部门
                jsonBody.put("deptid",eaTravel.getDeptId());
            }else{
                // 报销人部门=表体费用归属人部门
                jsonBody.put("deptid", iNcBdPsnjobService.getById(eaBookDetail.getPsnjobId()).getPkDept());
            }
            // 借款报销人=表体费用归属人
            jsonBody.put("jkbxr", eaBookDetail.getFygsr());
            // 收款对象=直接取表头收款对象
            jsonBody.put("paytarget", "0");
            // 报销单业务行标识=子表主键
            jsonBody.put("pk_busitem", "");
            // 报销单标识 =主表主键-n
            jsonBody.put("pk_jkbx", "");
            // 报销类型字段值数组
            jsonBody.put("pk_reimtype", eaBookDetail.getKind());
            // 收款人=直接取表头收款人
            jsonBody.put("receiver", eaTravel.getRecPersonId());
            // 行号=行号-n
            jsonBody.put("rowno", jsonArrayBody.size()+1);
            // 收支项目=费用项目
            jsonBody.put("szxmid", eaTravel.getIndexId());
            // 支付金额=实际报销金额
            jsonBody.put("ybje", actualEaAmt);
            // 支付本币金额 =实际报销金额
            jsonBody.put("zfbbje", actualEaAmt);
            // 支付金额=实际报销金额
            jsonBody.put("zfybje", actualEaAmt);
            jsonArrayBody.add(jsonBody);
        }

    }



    @Override
    public SysInterfaceLog bXApprove(ActBusiness actBusiness, String billNo) throws Exception {
        SysInterfaceLog sysInterfaceLog = new SysInterfaceLog();
        sysInterfaceLog.setBusinessNo(billNo);

            //查询差旅报销头
            EaTravel eaTravel = iEaTravelService.getById(actBusiness.getTableId());
            if(null==eaTravel){
                throw new RuntimeException("根据"+actBusiness.getTableId()+"TableId查询差旅报销空！");
            }
            EaListenerUtil.objectDefault(eaTravel, EaTravel.class);

            //查询差率报销表体费用明细
            List<EaBookDetail> eaBookDetails = eaBookDetailService.selectByMainId(eaTravel.getId());
            if(null==eaBookDetails||eaBookDetails.size()==0){
                throw new RuntimeException("根据"+eaTravel.getId()+"TableId查询差旅报销费用明细集合为空！");
    }


            /*
            进入start相关事件调用WSDL在做处理
            */


                //表头表体承载对象
                JSONObject jsonObject = new JSONObject();


                try {
                    //表头承载对象
                    JSONObject jsonHead = new JSONObject();

                    //根据表id查询任务记录最后审批人
                    ActZTask actZTask = iActZTaskService.getActZTaskByTableId(actBusiness.getProcInstId());

                    String userId = null;
                    int i = 0;
                    while (true){
                        i++;
                        userId = iActZTaskService.getActHiIdentitylinkById(actZTask.getProcInstId(), actZTask.getTaskId());

                        if(StrUtil.isNotEmpty(userId) || i==100){
                            break;
                        }
                        Thread.sleep(3000);
                    }
                    if(StrUtil.isEmpty(userId)){
                        throw new RuntimeException("根据表id查询任务记录最后审批人失败！");
                    }



                    /*
                    表头封装
                     */
                    // 审批人=最后审批人(财务)-用户主键
                    jsonHead.put("approver", actZTask.getOwnerId());
                    // 本币汇率=默认为1
                    jsonHead.put("bbhl", "1");
                    // 本币金额=实际报销金额
                    jsonHead.put("bbje", eaTravel.getActualPayAmt());
                    // 币种=人民币-币种主键，直接取人民币主键
                    jsonHead.put("bzbm", "1002Z0100000000001K1");
                    // 冲借款本币金额= -金额为0 否
                    jsonHead.put("cjkbbje", "0");
                    // 冲借款原币金额= -金额为0 否
                    jsonHead.put("cjkybje", "0");
                    // 创建人=创建人-用户主键
                    jsonHead.put("creator", eaTravel.getCreateBy());
                    // 原报销人部门=报销人部门-组织_部门
                    jsonHead.put("deptid", eaTravel.getDeptId());
                    // 报销人部门=报销人部门-组织_部门版本信息
                    jsonHead.put("deptid_v", eaTravel.getDeptId());
                    // 单据编号=单据编号
                    jsonHead.put("djbh", eaTravel.getBillNo());
                    // 单据大类=bx-bx
                    jsonHead.put("djdl", "bx");
                    // 单据类型编码=2641-差旅:2641
                    jsonHead.put("djlxbm", "2641");
                    // 单据日期=单据日期-2021-12-15 09:32:43
                    jsonHead.put("djrq", DateUtil.format(eaTravel.getBillDate(), "yyyy-MM-dd HH:mm:ss"));
                    // 单据状态=3-0=暂存，1=保存，2=审核，3=签字，-1=作废，
                    jsonHead.put("djzt", eaTravel.getState());
                    // 原费用承担单位=费用承担单位-组织
                    jsonHead.put("fydwbm", eaTravel.getCostCompCodeId());
                    // 费用承担单位=费用承担单位-组织_版本信息
                    jsonHead.put("fydwbm_v", eaTravel.getCostCompCodeId());
                    // 删除标志=0
                    jsonHead.put("dr", "0");
                    // 报销人单位 =表体费用归属人单位
                    jsonHead.put("dwbm", eaTravel.getCompanyCodeId());
                    // 报销人单位=报销人单位
                    jsonHead.put("dwbm_v", eaTravel.getCompanyCodeId());
                    // 附件张数=附件张数 否
                    jsonHead.put("fjzs", eaTravel.getAtNum().equals("") ? 0 : eaTravel.getAtNum());
                    // 原费用承担部门=费用承担部门-组织_部门
                    jsonHead.put("fydeptid", eaTravel.getCostDept());
                    // 费用承担部门=费用承担部门-组织_部门版本信息
                    jsonHead.put("fydeptid_v", eaTravel.getCostDept());
                    // 供应商=供应商-收款对象为供应商，供应商必填 否
                    jsonHead.put("hbbm", eaTravel.getRecPersonId());
                    // 还款本币金额= -金额为0
                    jsonHead.put("hkbbje", "0");
                    // 借款报销人=表体费用归属人
                    jsonHead.put("jkbxr", eaTravel.getPersonId());
                    // 结算方式=支付方式
                    jsonHead.put("jsfs", eaTravel.getPaymentMethod());
                    // 签字日期=最后审核人审核日期
                    jsonHead.put("jsr", actZTask.getOwnerId());
                    // 会计年度=单据日期年度
                    jsonHead.put("kjnd", "");
                    // 会计期间=单据日期月份
                    jsonHead.put("kjqj", "");
                    // 录入人=录入人-用户主键
                    jsonHead.put("operator", eaTravel.getCreateBy());
                    // 支付状态=3-3=支付完成
                    jsonHead.put("payflag", "3");
                    // 支付人=最后审批人(财务)
                    jsonHead.put("payman", actZTask.getOwnerId());
                    // 收款对象=直接取表头收款对象
                    jsonHead.put("paytarget", "0");
                    // pk_billtype=264X-264X
                    jsonHead.put("pk_billtype", "264X");
                    // 集团=集团
                    jsonHead.put("pk_group", "0001A110000000000CLJ");
                    // 财务组织=费用承担单位
                    jsonHead.put("pk_fiorg", eaTravel.getCostCompCodeId());
                    // 借款报销单标识 =主表主键
                    jsonHead.put("pk_jkbx", "");
                    // 原报销单位=费用承担单位
                    jsonHead.put("pk_org", eaTravel.getCostCompCodeId());
                    // 报销单位=费用承担单位
                    jsonHead.put("pk_org_v", eaTravel.getCostCompCodeId());
                    // 原付款单位=费用承担单位
                    jsonHead.put("pk_payorg", eaTravel.getCostCompCodeId());
                    // 付款单位=费用承担单位
                    jsonHead.put("pk_payorg_v", eaTravel.getCostCompCodeId());
                    // 交易类型=NC交易类型主键
                    jsonHead.put("pk_tradetypeid", "0001A110000000002AVD");
                    // 收款人=收款人-收款对象为员工，收款人必填
                    jsonHead.put("receiver", eaTravel.getRecPersonId());
                    // 审批状态=审批通过-0=审批未通过，1=审批通过，2=审批进行中，3=提交，-1=自由，
                    jsonHead.put("spzt", "-1");
                    // 生效标志=1-0=未生效，1=已生效，
                    jsonHead.put("sxbz", "1");
                    // 收支项目=费用项目
                    jsonHead.put("szxmid", eaTravel.getIndexId());
                    // 合计金额=实际付款金额
                    jsonHead.put("total", eaTravel.getActualPayAmt());
                    // 原币金额=实际付款金额
                    jsonHead.put("ybje", eaTravel.getActualPayAmt());
                    // 出差类型=自定义项14
                    jsonHead.put("zyx14", iSysDictService.queryDictTextByKey("ea_business_type",eaTravel.getType().toString()));
                    // 目的地=自定义项15
                    jsonHead.put("zyx15", iEaRegionService.getById(eaTravel.getRegionId()).getName());
                    // 支付本币金额 =实际报销金额
                    jsonHead.put("zfbbje", eaTravel.getActualPayAmt());
                    // 支付金额=实际报销金额
                    jsonHead.put("zfybje", eaTravel.getActualPayAmt());
                    // 事由=事由
                    jsonHead.put("zy", eaTravel.getCause());
                    //最后审批人编码
                    jsonHead.put("actionCode", "APPROVE" + userId);

                    jsonObject.put("head", jsonHead);
                    /*
                    表头封装结束
                     */

                    /*
                    表体封装
                     */
                    JSONArray jsonArrayBody = new JSONArray();
                    for (int a = 0; a < eaBookDetails.size(); a++) {

                        //获取费用明细
                        EaBookDetail eaBookDetail = eaBookDetails.get(a);
                       EaListenerUtil.objectDefault(eaBookDetail, EaBookDetail.class);

                        List<Map<String, Object>> billDetailList=null;

                        try {
                            //获取根据发票id获取发票明细集合
                            billDetailList = iEaBillService.getBillDetailList(eaBookDetail.getFpid());
                        }catch (Exception e){
                            throw new RuntimeException("获取发票明细失败!(StackTrace="+EaListenerUtil.formatStackTrace(e)+")");
                        }

                        //表体封装
                        if (billDetailList!=null||billDetailList.size()>0) {
                            try{
                                JSONArray detaijsonObject = JSON.parseArray(JSON.toJSONString(billDetailList));
                                bodySet(eaTravel, eaBookDetail, detaijsonObject, jsonArrayBody);
                            }catch (Exception e){
                                throw new RuntimeException("fybx表体封装错误!(StackTrace="+EaListenerUtil.formatStackTrace(e)+")");
                            }
                        } else {
                            throw new RuntimeException("获取发票明细空！");
                        }


                    }

                    jsonObject.put("body", jsonArrayBody);
                    /*
                    表体封装结束
                     */


//                    WSVO wsvo=null;

                    //调用WSDL
                    WSVO wsvo = NCWebService.sendToWS(nCUrl, WSEnum.TRAVElEXPENSEBX, jsonObject.toJSONString());

                    //日志保存
                    if(!wsvo.getStatus()){
                        throw new RuntimeException(wsvo.getMessage());
                    }
                    sysInterfaceLog.setState("1");
                    sysInterfaceLog.setDisposeState("0");
                    sysInterfaceLog.setResult(wsvo.getMessage());
                } catch (Exception e) {
                    sysInterfaceLog.setState("0");
                    sysInterfaceLog.setDisposeState("1");
                    sysInterfaceLog.setResult(e.getMessage());
                }
        sysInterfaceLog.setContent(jsonObject.toJSONString());
        sysInterfaceLog.setCreateTime(new DateTime());
        return sysInterfaceLog;
    }


}
